<?php
/* ================================================================================
 * Form Validater Class 
 *
 * fvr.class.php: This class is to validate data on a form.
 *
 * Author: Eric Hendrickson (enhendrickson@liberty.edu)
 * Date: 12/10/2004
   ================================================================================ */


class FormValidation
{
	var $fdf_xml_raw;
	var $fdf_xml_file;  
	var $form_name;
	var $return_url;
	var $rules_obj;
	
	function FormValidation()
	{
		$this->fdf_xml_file = "";
		$this->fdf_xml_raw = "";
		$this->form_name = "";
		$this->return_rul = "";
		$this->rules_obj = NULL;
	}
	
	function validateForm($fdf_file)
	{
		if($fdf_file!="")
		{
			$this->fdf_xml_file = $fdf_file;	
		}
		else
		{
			$this->showError("Fatal Error: No FDF file was provided to the fvr class!");
			exit();
		}
		
		$this->loadXML();
		$this->setFDFobjs();
		$isValid = $this->checkIsValid();
		if(!$isValid)
		{
			print '<script type="text/javascript" language="JavaScript1.2">frmValidate_' . $this->form_name . '.submit();</script>';
			die();
		}
	}
	
	function checkIsValid()
	{
		$rules_index = 0;
		$error_count = 0;
		print '<form name="frmValidate_' . $this->form_name . '" method="post" action="' . $this->return_url . '">';
		while($rules_index < sizeof($this->rules_obj))
		{
			if($this->rules_obj[$rules_index]->children[$this->findElementByName("REQUIRED",	$rules_index)]->contents == "0" && 
					$_POST[$this->rules_obj[$rules_index]->children[$this->findElementByName("FIELD",	$rules_index)]->contents] == "")
			{
				$rules_index++;
				continue;
			}
			if($this->rules_obj[$rules_index]->children[$this->findElementByName("REQUIRED",	$rules_index)]->contents == "1" && 
					$_POST[$this->rules_obj[$rules_index]->children[$this->findElementByName("FIELD",	$rules_index)]->contents] == "")
			{
				print '<input type="hidden" value="' . $this->rules_obj[$rules_index]->children[$this->findElementByName("DISPLAY",	$rules_index)]->contents . ' cannot be empty." 
				  name="err_' . $this->rules_obj[$rules_index]->children[$this->findElementByName('FIELD',	$rules_index)]->contents . '">';
				$error_count++;
			}
			else
			{
				if(strlen($_POST[$this->rules_obj[$rules_index]->children[$this->findElementByName("FIELD",	$rules_index)]->contents]) > $this->rules_obj[$rules_index]->children[$this->findElementByName("LENGTH",	$rules_index)]->contents)
				{
					print '<input type="hidden" value="' . $this->rules_obj[$rules_index]->children[$this->findElementByName("DISPLAY",	$rules_index)]->contents . ' has too many characters." 
						name="err_' . $this->rules_obj[$rules_index]->children[$this->findElementByName("FIELD",	$rules_index)]->contents . '">';
					$error_count++;
				}
				else
				{
					if(!$this->validateFieldType($_POST[$this->rules_obj[$rules_index]->children[$this->findElementByName("FIELD",	$rules_index)]->contents],
							$this->rules_obj[$rules_index]->children[$this->findElementByName("TYPE",	$rules_index)]->contents))
					{
						print '<input type="hidden" value="' . $this->rules_obj[$rules_index]->children[$this->findElementByName("DISPLAY",	$rules_index)]->contents . ' is not in the correct format."
										name="err_' . $this->rules_obj[$rules_index]->children[$this->findElementByName("FIELD",	$rules_index)]->contents . '">';
						$error_count++;
					}
					else
					{
						if($this->rules_obj[$rules_index]->children[$this->findElementByName("TYPE",	$rules_index)]->contents == "Password")
						{
							if($this->rules_obj[$rules_index+1]->children[$this->findElementByName("TYPE",	$rules_index+1)]->contents != "Password")
							{
								print '<p style="font-face:Verdana;font-size:12px;color:##FF0000;">FDF Error.  Password type given without matching type.  Please contact your administrator.</p>';
								exit();
							}
							if($_POST[$this->rules_obj[$rules_index]->children[$this->findElementByName("FIELD",	$rules_index)]->contents] != $_POST[$this->rules_obj[$rules_index+1]->children[$this->findElementByName("FIELD",	$rules_index+1)]->contents])
							{
								print '<input type="hidden" value="' . $this->rules_obj[$rules_index]->children[$this->findElementByName("DISPLAY",	$rules_index)]->contents . ' did not match."
												name="err_' . $this->rules_obj[$rules_index]->children[$this->findElementByName("FIELD",	$rules_index)]->contents . '">';
								$error_count++;
								$rules_index++;
							}
						}
					}
				}
			}

			print '<input type="hidden" value="' . htmlentities(stripslashes($_POST[$this->rules_obj[$rules_index]->children[$this->findElementByName("FIELD",	$rules_index)]->contents]))
				. '" name="val_' . $this->rules_obj[$rules_index]->children[$this->findElementByName("FIELD",	$rules_index)]->contents . '">';
			$rules_index++;
		}	
		print '</form>';
		
		if($error_count > 0)
		{
			//the form is not valid
			return false;
		}
		else
		{
			//the form is valid
			return true;
		}
	}
	
	function validateFieldType($string_to_validate, $type)
	{
		if(substr($type,0,7) == "REGEX::")
		{
			$regex = substr($type,7,strlen($type));
			$type = 'Regex';
		} 
		
		switch($type)
		{
			case 'Regex':
			{
				$isValid = ereg($regex,$string_to_validate,$regs);
				if(strcmp(trim($regs[0]),trim($string_to_validate)) != 0)
				{
					$isValid = false;
				}
				break;
			}
			case 'Date':
			{
				$isValid = ereg("(((([0]?[469]|11)[(\/)-](0[1-9]|[12][0-9]|30))|(([0]?[13578]|1[02])[(\/)-](0[1-9]|[12][0-9]|31))|([0]?[2][(\/)-](0[1-9]|[1][0-9]|2[0-8])))[(\/)-][0-9][0-9][0-9][0-9])|([0]?[2][(\/)-]29[(\/)-][0-9][0-9]([02468][048]|[13579][26]))",$string_to_validate,$regs);
				if(strcmp(trim($regs[0]),trim($string_to_validate)) != 0)
				{
					$isValid = false;
				}
				break;
			}
			case 'Email':
			{
				$isValid = ereg("^([_a-zA-Z0-9-]+)(\.[_a-zA-Z0-9-]+)*@([a-zA-Z0-9-]+)(\.[a-zA-Z0-9-]+)*(\.[a-zA-Z]{2,4})$",$string_to_validate,$regs);
				if(strcmp(trim($regs[0]),trim($string_to_validate)) != 0)
				{
					$isValid = false;
				}
				break;
			}
			case 'Phone':
			{
				$isValid = ereg("^[\(]?([0-9]{3})?[\)]?[\-]?[0-9]{3}[\-]?[0-9]{4}$",$string_to_validate,$regs);
				if(strcmp(trim($regs[0]),trim($string_to_validate)) != 0)
				{
					$isValid = false;
				}
				break;
			}
			case 'Int':
			{
				$isValid = (is_numeric($string_to_validate) && $string_to_validate > -9223372036854775808 && $string_to_validate < 9223372036854775807);
			}
			case 'Char':
			{
				$isValid = true;
				break;
			}
		}

		if(!$isValid)
		{
			return false;
		}
		else
		{
			return true;
		}
	}
	
	function findElementByName($name,$ruleid)
	{
		$name_index=0;
		while($this->rules_obj[$ruleid]->children[$name_index]->name != $name && $name_index < sizeof($this->rules_obj[$ruleid]->children))
		{
			$name_index++;
		}
		return $name_index;
	}
	
	function setFDFobjs()
	{
		//thanks talraith at withouthonor dot com (http://us2.php.net/manual/en/ref.xml.php)
		//xlm_doc.class.php written by above author

		include_once('Data/XMLDoc.php');
		
		$xml = new XMLDoc($this->fdf_xml_raw);
		$xml->parse();

		$this->return_url = htmlentities($xml->xml_index[0]->children[0]->contents);
		$this->form_name = $xml->xml_index[0]->children[1]->contents;
		
		$xml_index = 2;
		$rules_index = 0;
		while($xml_index < sizeof($xml->xml_index[0]->children))
		{
			$this->rules_obj[$rules_index] = $xml->xml_index[0]->children[$xml_index];
			$xml_index++;
			$rules_index++;
		}			
	}
	
	function loadXML()
	{
		$this->fdf_xml_raw = file_get_contents($this->fdf_xml_file);
		
		if($this->fdf_xml_raw == "")
		{
			$this->showError("Fatal Error:  '" . $this->fdf_xml_file . "' did not load!");
			exit();
		}
	}

	function showError($err)
	{
		print $err . "<br>";
	}
	
	function getPostIfSet($post_var_name)
	{
		if(isset($_POST[$post_var_name]))
		{
			return htmlentities(stripslashes($_POST[$post_var_name]));
		}
		else
		{
			return "";
		}
	}
}
?>
